

var articleService = require("../service/article-service");
var db = require('../db');
var jwt = require('jsonwebtoken');
var router = require('express').Router();
var webResult = require('../web-result');
var path = require("path");
var fs = require("fs");

const pageSize = 10;


const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const validateSchema = (xml, xsdSchema) => import("xsd-validator").then(module => module.default.default(xml, xsdSchema));
const articleContentXSD = fs.readFileSync(path.join(__dirname, "../public/schema/article-content.xsd"), "utf-8");

// RSS
const RSS = require("../rss");


// Prisma
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();


/**
 * 获取所有 sort
 */
router.get('/article/sort/all', async (request, response) => {
	db.query("select * from article_sort order by id asc")
	.then(res => {
		response.send(webResult.success(res));
	});
})


/**
 * 分页获取 sort
 */
router.get('/article/sort/page/:page', async (request, response) => {
	const { page } = request.params;

	db.query("select * from article_sort order by id asc limit ?, ?", [pageSize * (page - 1), pageSize])
	.then(res => {
		response.send(webResult.success(res));
	})
})



/**
 * 通过 id 获取 article
 */
router.get('/article/:id', async function(request, response, next) {
  	const id = parseInt(request.params.id);
	articleService.getArticleByID(id)
	.then(article => {
		if (!article)
		{
			response.send(webResult.failed());
			return;
		}
		response.send(webResult.success(article));
	});
});


/**
 * 分页获取 article 信息
 */
router.get('/article/page/:page', async (request, response) => {
	const { page } = request.params;

	db.query("select id, title, date, sort_id from article order by publish_time desc limit ?, ?", [pageSize * (page - 1), pageSize])
	.then(async res => {

		for (let index = 0; index < res.length; index++) {
			const element = res[index];
			element.sort_name = await articleService.getSortNameByID(element.sort_id);
			element.sort = element.sort_name;
			// element.date = element.date.getFullYear() + "/" + (element.date.getMonth() + 1) + "/" + element.date.getDate();
			element.date = `${element.date.getFullYear()}/${(element.date.getMonth() + 1)}/${element.date.getDate()}`;
			// element.date = element.date.toLocaleDateString("zh-Hans-CN");
		}
		response.send(webResult.success(res));
	})
})


/**
 * 通过 分类ID 或 分类名 分页获取 article 信息
 */
router.get('/article/sort/:sort/page/:page', async (request, response) => {
	const { page } = request.params;
	let { sort } = request.params;

	let sortID = parseInt(sort);
	if (isNaN(sortID))
		sortID = await articleService.getSortIDByName(sort);
	else
		sort = await articleService.getSortNameByID(sortID);
	
	if (!sortID)
	{
		response.send(webResult.failed(undefined, "不存在的分类"));
		return;
	}
	db.query("select id, title, date from article where sort_id = ? order by publish_time desc limit ?, ?", [sortID, pageSize * (page - 1), pageSize])
	.then(async res => {

		for (let index = 0; index < res.length; index++) {
			const element = res[index];
			element.sort = sort;
			element.sort_name = sort;
			// element.date = element.date.getFullYear() + "/" + (element.date.getMonth() + 1) + "/" + element.date.getDate();
			element.date = `${element.date.getFullYear()}/${(element.date.getMonth() + 1)}/${element.date.getDate()}`;
			// element.date = element.date.toLocaleDateString("zh-Hans-CN");
		}
		response.send(webResult.success(res));
	})
})


/**
 * 通过 标题 分页搜索 article 信息
 */
router.get('/article/search/title/:title/page/:page', async (request, response) => {
	const { title, page } = request.params;

	db.query("select id, title, date, sort_id from article where title like ? order by publish_time desc limit ?, ?", [`%${title}%`, pageSize * (page - 1), pageSize])
	.then(async res => {

		for (let index = 0; index < res.length; index++) {
			const element = res[index];
			element.sort_name = await articleService.getSortNameByID(element.sort_id);
			element.sort = element.sort_name;
			// element.date = element.date.getFullYear() + "/" + (element.date.getMonth() + 1) + "/" + element.date.getDate();
			element.date = `${element.date.getFullYear()}/${(element.date.getMonth() + 1)}/${element.date.getDate()}`;
			// element.date = element.date.toLocaleDateString("zh-Hans-CN");
		}
		response.send(webResult.success(res));
	})
})



/**
 * 搜索 分类名 分页搜索 article 信息
 */
router.get('/article/search/sort/:sort/page/:page', async (request, response) => {
	const { sort, page } = request.params;

	const sortIDs = await articleService.searchSortIDByName(sort);
	if (!sortIDs || sortIDs.length === 0)
	{
		response.send(webResult.success([]));
		return;
	}
	const countM1 = sortIDs.length - 1;
	let sortIDsSql = "";
	for (let index = 0; index < sortIDs.length; index++) {
		const id = sortIDs[index];
		if (index !== countM1)
			sortIDsSql += `sort_id = ${id} or`;
		else
			sortIDsSql += `sort_id = ${id}`;
	}

	db.query(`select id, title, date from article where ${sortIDsSql} order by publish_time desc limit ?, ?`, [pageSize * (page - 1), pageSize])
	.then(async res => {

		for (let index = 0; index < res.length; index++) {
			const element = res[index];
			element.sort = sort;
			element.sort_name = sort;
			// element.date = element.date.getFullYear() + "/" + (element.date.getMonth() + 1) + "/" + element.date.getDate();
			element.date = `${element.date.getFullYear()}/${(element.date.getMonth() + 1)}/${element.date.getDate()}`;
			// element.date = element.date.toLocaleDateString("zh-Hans-CN");
		}
		response.send(webResult.success(res));
	})
})


// 用户ID 获取 article 信息
router.get("/article/user/id/:id", async(request, response) => {
	const { id } = request.params;
	db.query("select id, title, date, sort_id, content from article where publisher_id = ? order by update_time desc", [id])
	.then(async result => {
		for (let index = 0; index < result.length; index++) {
			const element = result[index];
			element.sort_name = await articleService.getSortNameByID(element.sort_id);
			element.sort = element.sort_name;
			// element.date = element.date.getFullYear() + "/" + (element.date.getMonth() + 1) + "/" + element.date.getDate();
			element.date = `${element.date.getFullYear()}/${(element.date.getMonth() + 1)}/${element.date.getDate()}`;
			// element.date = element.date.toLocaleDateString("zh-Hans-CN");
		}
		response.send(webResult.success(result, "获取成功"));
	})
	.catch(e => {
		console.error(e);
		response.send(webResult.failed(undefined, "获取失败，内部错误"));
	});
});

// 用户ID 分页获取 article 信息
router.get("/article/user/id/:id/page/:page", async (request, response) => {
	const { id, page } = request.params;
	db.query("select id, title, date, sort_id, content from article where publisher_id = ? order by update_time desc limit ?, ?", [id, pageSize * (page - 1), pageSize])
	.then(async result => {
		for (let index = 0; index < result.length; index++) {
			const element = result[index];
			element.sort_name = await articleService.getSortNameByID(element.sort_id);
			element.sort = element.sort_name;
			// element.date = element.date.getFullYear() + "/" + (element.date.getMonth() + 1) + "/" + element.date.getDate();
			element.date = `${element.date.getFullYear()}/${(element.date.getMonth() + 1)}/${element.date.getDate()}`;
			// element.date = element.date.toLocaleDateString("zh-Hans-CN");
		}
		response.send(webResult.success(result, "获取成功"));
	})
	.catch(e => {
		console.error(e);
		response.send(webResult.failed(undefined, "获取失败，内部错误"));
	});
});

// 用户昵称 获取 article 信息
router.get("/article/user/nickname/:nickname", async(request, response) => {
	const { nickname } = request.params;
	const uid = await articleService.getUserIDByNickname(nickname);
	db.query("select id, title, date, sort_id, content from article where publisher_id = ? order by update_time desc", [uid])
	.then(async result => {
		for (let index = 0; index < result.length; index++) {
			const element = result[index];
			element.sort_name = await articleService.getSortNameByID(element.sort_id);
			element.sort = element.sort_name;
			// element.date = element.date.getFullYear() + "/" + (element.date.getMonth() + 1) + "/" + element.date.getDate();
			element.date = `${element.date.getFullYear()}/${(element.date.getMonth() + 1)}/${element.date.getDate()}`;
			// element.date = element.date.toLocaleDateString("zh-Hans-CN");
		}
		response.send(webResult.success(result, "获取成功"));
	})
	.catch(e => {
		console.error(e);
		response.send(webResult.failed(undefined, "获取失败，内部错误"));
	});
});

// 用户昵称 分页获取 article 信息
router.get("/article/user/nickname/:nickname/page/:page", async (request, response) => {
	const { nickname, page } = request.params;
	const uid = await articleService.getUserIDByNickname(nickname);
	db.query("select id, title, date, sort_id, content from article where publisher_id = ? order by update_time desc limit ?, ?", [uid, pageSize * (page - 1), pageSize])
	.then(async result => {
		for (let index = 0; index < result.length; index++) {
			const element = result[index];
			element.sort_name = await articleService.getSortNameByID(element.sort_id);
			element.sort = element.sort_name;
			// element.date = element.date.getFullYear() + "/" + (element.date.getMonth() + 1) + "/" + element.date.getDate();
			element.date = `${element.date.getFullYear()}/${(element.date.getMonth() + 1)}/${element.date.getDate()}`;
			// element.date = element.date.toLocaleDateString("zh-Hans-CN");
		}
		response.send(webResult.success(result, "获取成功"));
	})
	.catch(e => {
		console.error(e);
		response.send(webResult.failed(undefined, "获取失败，内部错误"));
	});
});

// 用户名 获取 article 信息
router.get("/article/user/username/:username", async(request, response) => {
	const { username } = request.params;
	const uid = await articleService.getUserIDByUsername(username);
	db.query("select id, title, date, sort_id, content from article where publisher_id = ? order by update_time desc", [uid])
	.then(async result => {
		for (let index = 0; index < result.length; index++) {
			const element = result[index];
			element.sort_name = await articleService.getSortNameByID(element.sort_id);
			element.sort = element.sort_name;
			// element.date = element.date.getFullYear() + "/" + (element.date.getMonth() + 1) + "/" + element.date.getDate();
			element.date = `${element.date.getFullYear()}/${(element.date.getMonth() + 1)}/${element.date.getDate()}`;
			// element.date = element.date.toLocaleDateString("zh-Hans-CN");
		}
		response.send(webResult.success(result, "获取成功"));
	})
	.catch(e => {
		console.error(e);
		response.send(webResult.failed(undefined, "获取失败，内部错误"));
	});
});

// 用户名 分页获取 article 信息
router.get("/article/user/username/:username/page/:page", async (request, response) => {
	const { username, page } = request.params;
	const uid = await articleService.getUserIDByUsername(username);
	db.query("select id, title, date, sort_id, content from article where publisher_id = ? order by update_time desc limit ?, ?", [uid, pageSize * (page - 1), pageSize])
	.then(async result => {
		for (let index = 0; index < result.length; index++) {
			const element = result[index];
			element.sort_name = await articleService.getSortNameByID(element.sort_id);
			element.sort = element.sort_name;
			// element.date = element.date.getFullYear() + "/" + (element.date.getMonth() + 1) + "/" + element.date.getDate();
			element.date = `${element.date.getFullYear()}/${(element.date.getMonth() + 1)}/${element.date.getDate()}`;
			// element.date = element.date.toLocaleDateString("zh-Hans-CN");
		}
		response.send(webResult.success(result, "获取成功"));
	})
	.catch(e => {
		console.error(e);
		response.send(webResult.failed(undefined, "获取失败，内部错误"));
	});
});


// 用户ID 获取发布的 article 数量
router.get("/article/count/user/id/:id", async (request, response) => {
	const userID = parseInt(request.params.id);
	if (Number.isNaN(userID))
	{
		response.send(webResult.failed(undefined, "id is not a number"));
		return;
	}
	const count = await prisma.article.count({
		where: {
			publisher_id: userID
		}
	});
	response.send(webResult.success(count));
});

// 用户名 获取发布的 article 数量
router.get("/article/count/user/username/:username", async (request, response) => {
	const username = request.params.username;
	if (!username)
	{
		response.send(webResult.failed(undefined, "username is null"));
		return;
	}

	const publisher = await prisma.user.findUnique({
		select: {
			id: true
		},
		where: {
			username: username
		}
	});
	if (!publisher)
	{
		response.send(webResult.failed(undefined, "user is not exists"));
		return;
	}

	const count = await prisma.article.count({
		where: {
			publisher_id: publisher.id
		}
	});
	response.send(webResult.success(count));
});



// 发布文章
router.post('/article', async (request, response) => {
	const token = request.headers.token;
	const uid = jwt.decode(token).id;
	let { author } = request.body;
	const { sort, title, date, content } = request.body;
	let { sort_id } = request.body;

	if (!title || !date || !content)
	{
		response.send(webResult.failed(undefined, "参数不足"));
		return;
	}
	if (!sort_id && !sort)
	{
		response.send(webResult.failed(undefined, "参数不足"));
		return;
	}


	if (!sort_id)
		sort_id = await getSortIDByName(sort);
	if (!sort_id)
	{
		response.send(webResult.failed(undefined, "不存在的分类"));
		return;
	}

	if (!author)
		author = null;


	validateSchema(content, articleContentXSD)
	.then(valid => {
		
		// true
		if (valid === true) {
			// 将 数据 插入 数据库

			const xmlDOM = new JSDOM(`<body>${content}</body>`);
			const contentElement = xmlDOM.window.document.querySelector("content") || xmlDOM.window.document.querySelector("main");
			// console.log(contentElement);

			db.transactionQuery(
				[
					"insert into article (author, publisher_id, sort_id, title, date, content) values(?, ?, ?, ?, ?, ?)",
					// "select id from article where publisher_id = ? and sort_id = ? and title = ? and date = ? order by publish_time desc limit 1"
					"select last_insert_id() as id"
				],
				[
					[author, uid, sort_id, title, date, contentElement.textContent],
					// [id, sort_id, title, date]
				]
			)
			.then(async resultArray => {
				
				const article = resultArray[1][0];
				try {
					// 转 json 存储
					const contentArray = articleService.articleContentElement2Array(contentElement);
					const jsonPath = articleService.getArticleContentPath(uid, sort_id, article.id);
					const dirPath = path.dirname(jsonPath);
					if (!fs.existsSync(dirPath))
						fs.mkdirSync(dirPath, { recursive: true });
					fs.writeFileSync(
						jsonPath,
						JSON.stringify(contentArray),
						"utf-8"
					);

					response.send(webResult.success(undefined, "发布成功"));
					RSS.makeRSSFile();
				} catch(e) {
					console.error(e);
					db.query("delete from article where id = ?", [article.id])
					.then(result => {
						if (result.affectedRows === 0)
							db.query("delete from article where id = ?", [article.id])
					})
					.catch(err => {
						console.error(err);
						db.query("delete from article where id = ?", [article.id])
					});
					response.send(webResult.failed(undefined, "发布失败"));
				}
				
			})
			.catch(err => {
				console.error(err);
				response.send(webResult.failed(undefined, "发布失败"));
			});
			

		}
		else {
			console.error(valid);
			response.send(webResult.failed(undefined, "发布失败，content格式错误"));
		}
	});

});



router.put('/article', async (request, response) => {
	const token = request.headers.token;
	const uid = jwt.decode(token).id;
	const { id, sort, title, date, content } = request.body;
	let { sort_id } =  request.body;

	if (!id)
	{
		response.send(webResult.failed(undefined, "参数不足"));
		return;
	}
	if (!sort && !sort_id && !title && !date && !content)
	{
		response.send(webResult.failed(undefined, "参数不足"));
		return;
	}

	db.query("select id, publisher_id, sort_id, title from article where id = ?", [id])
	.then(async result => {
		if (!result)
		{
			response.send(webResult.failed(undefined, "更新失败，文章不存在"));
			return;
		}

		const article = result[0];
		if (article.publisher_id !== uid)
		{
			response.send(webResult.failed(undefined, "更新失败，文章作者不是当前登录的用户"));
			return;
		}

		let contentElement = undefined;
		let sql = "update article set ";
		if (!sort_id && sort)
		{
			sort_id = await getSortIDByName(sort);
			sql += `sort_id = "${sort_id}",`;
		}
		else if(sort_id)
		{
			sql += `sort_id = "${sort_id}",`;
		}

		if (title)
		{
			sql += `title = "${title}",`;
		}
		if (date)
		{
			sql += `date = "${date}",`;
		}
		if (content)
		{
			validateSchema(content, articleContentXSD)
			.then(valid => {
				if (valid === true)
				{
					const xmlDOM = new JSDOM(`<body>${content}</body>`);
					contentElement = xmlDOM.window.document.querySelector("content") || xmlDOM.window.document.querySelector("main");
					sql += `content = "${contentElement.textContent}"`;
				}
				else {
					console.error(valid);
					response.send(webResult.failed(undefined, "content格式错误"));
				}
			})
			.catch(e => {
				console.error(e);
				response.send(webResult.failed(undefined, "content格式错误"));
			})
		}
		if (sql[sql.length - 1] === ",")
		{
			sql[sql.length - 1] = ' ';
			sql += ` where id = "${id}"`;
		}


		db.query(sql)
		.then(async result => {
			if (result.affectedRows === 0)
			{
				response.send(webResult.failed(undefined, "更新失败，内部错误"));
				return;
			}

			if (contentElement)
			{
				try {
					const contentArray = articleService.articleContentElement2Array(contentElement);
					const jsonPath = articleService.getArticleContentPath(uid, article.sort_id, article.id);
					fs.writeFileSync(
						jsonPath,
						JSON.stringify(contentArray),
						"utf-8"
					);
					db.query("update article set update_time = now()");
					response.send(webResult.failed(undefined, "更新成功"));
				} catch (e) {
					console.error(e);
					response.send(webResult.failed(undefined, "更新失败，内部错误"));
					return;
				}
			}
		})
		.catch(e => {
			console.error(e);
			response.send(webResult.failed(undefined, "更新失败，内部错误"));
		})
	})
	.catch(e => {
		console.error(e);
		response.send(webResult.failed(undefined, "更新失败，内部错误"));
	});

});


router.delete('/article', async (request, response) => {
	const token = request.headers.token;
	const uid = jwt.decode(token).id;
	const { id } = request.body;
	if (!id)
	{
		response.send(webResult.failed(undefined, "id为空"));
		return;
	}

	db.query("delete from article where publisher_id = ? and id = ?", [uid, id])
	.then(result => {
		if (result.affectedRows === 0)
		{
			response.send(webResult.failed(undefined, "删除失败"));
			return;
		}
		response.send(webResult.success(undefined, "删除成功"));
	})
	.catch(e => {
		console.error(e);
		response.send(webResult.failed(undefined, "删除失败"));
	});

});


module.exports = router;

